package com.itheima.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.mapper.OperateLogMapper;
import com.itheima.pojo.OperateLog;
import com.itheima.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;

/**
 * 记录员工管理接口的日志信息
 */
@Component
@Aspect
@Slf4j // 打印日志
public class LogAspect {
    @Autowired  // java对象和json相互转换的工具类  将下面数组转换成String类型的json对象
    private ObjectMapper objectMapper;  // IDEA识别错误

    @Autowired
    private HttpServletRequest request;



    @Autowired  // 注入Mapper层
    private OperateLogMapper operateLogMapper;



// 定义环绕通知,记录员工管理接口的日志信息
    @Around("@annotation(com.itheima.annotation.Log)")
    public Object recordLog(ProceedingJoinPoint pjp) throws Throwable {

        // 1. private Integer operateUser;        // 获取操作人ID
        String jwt =request.getHeader("token");
        // 验证jwt,得到载荷中的id
        Claims claims = JwtUtils.parseJWT(jwt);
        Integer operateUser = (Integer) claims.get("id");  // 强转

        // 2. private LocalDateTime operateTime;  // 获取操作时间
        LocalDateTime operateTime=LocalDateTime.now();

        // 3. private String className;           // 获取操作类名
        String className = pjp.getTarget().getClass().getName();

        // 4. private String methodName;          // 获取操作方法名
        String methodName = pjp.getSignature().getName();

        // 5. private String methodParams;        // 获取操作方法参数
        // 这里 getArgs(); 方法返回的是数组,需要强转成字符串
        Object[] args = pjp.getArgs();
        String methodParams = objectMapper.writeValueAsString(args);

        // 6. private String returnValue;         // 获取操作方法返回值
        long start = System.currentTimeMillis();  // 7.1 获取开始时间
        Object result = pjp.proceed(); // result对象
        //  调用objectMapper的方法转换String类型的json对象
        String returnValue = objectMapper.writeValueAsString(result);
        long end = System.currentTimeMillis();    // 7.2 获取结束时间

        // 7. private Long costTime;              // 获取操作耗时
        Long costTime = end-start;


        // 8.将以上数据封装成OperateLog对象,调用OperateLogMapper 方法添加到表中
        OperateLog operateLog = new OperateLog(null, operateUser, operateTime, className, methodName, methodParams, returnValue, costTime);

        operateLogMapper.insert(operateLog);
        return result;
    }
}
